
import datetime
from enum import IntEnum
from sqlalchemy import Column, String, Integer, DateTime, Boolean, create_engine, Enum, JSON, DECIMAL, Text, func, delete, desc, update
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import declarative_base, sessionmaker
import uuid
from typing import Type, Generic, Any, List
from sqlalchemy.ext.asyncio import AsyncSession

sync_engine = create_engine("mysql+mysqlconnector://root:new_password@127.0.0.1:3306/{{Snake .projectName}}", pool_size=20, max_overflow=10)
Base = declarative_base()

class BasicsModel():
    id = Column(String(255), primary_key=True)
    remarks = Column(String(255))
    createdAt = Column(DateTime, default=datetime.datetime.now)
    updatedAt = Column(DateTime, default=datetime.datetime.now)

class TurnDict:
    # 单个对象转成map方法1
    def to_dict(self):
        model_dict = dict(self.__dict__)
        del model_dict['_sa_instance_state']
        return model_dict

    Base.to_dict = to_dict

    # 单个对象转成map方法2
    def single_to_dict(self):
        return {c.name: getattr(self, c.name) for c in self.__table__.columns}

    # 多个对象转成map
    def dobule_to_dict(self):
        result = {}
        for key in self.__mapper__.c.keys():
            if getattr(self, key) is not None:
                result[key] = str(getattr(self, key))
            else:
                result[key] = getattr(self, key)
        return result

class Status(IntEnum):
    # 禁用
    DISABLE = 0
    # 启用
    VALID = 1

# 配合多个对象使用的函数
def to_json(all_vendors):
    v = [ven.dobule_to_dict() for ven in all_vendors]
    return v

def create_table_all():
    Base.metadata.create_all(sync_engine)

def drop_table_all():
    Base.metadata.drop_all(sync_engine)

SyncSession = sessionmaker(bind=sync_engine)

def get_sync_db():
    return SyncSession()

async def insert_pojo(session: AsyncSession, Pojo: Type[Base], obj_dict: dict):
    session.add(Pojo(**obj_dict))

async def find_pojos(session: AsyncSession, Pojo: Type[Base], query, obj):
    pojo_list = (await session.execute(query.order_by(desc(Pojo.created_at)).offset(
        (obj.page_no - 1) * obj.page_size).limit(obj.page_size))).scalars().all()

    return pojo_list

async def update_pojo(session: AsyncSession, Pojo: Type[Base], obj_dict: dict):
    await session.execute(update(Pojo).where(Pojo.id == obj_dict["id"]), obj_dict)

async def delete_pojo(session: AsyncSession, Pojo: Type[Base], id: str):
    await session.execute(delete(Pojo).where(Pojo.id == id))

async def insert_pojo_by_many(session: AsyncSession, id_list: List[str], obj_dict1: dict, Pojo2: Type[Base], field2: str, field3: str):
    obj_dict2_list = []
    for id in id_list:
        # # 方式一:
        # obj_dict2 = {
        #     "id": uuid.uuid1().__str__(),
        #     field2: obj_dict1["id"],
        #     field3: id,
        #     "remarks": obj_dict1["remarks"]
        # }
        # obj_dict2_list.append(Pojo2(**obj_dict2))

        # 方式二:
        p2 = Pojo2()
        p2.id = uuid.uuid1().__str__()
        setattr(p2, field2, obj_dict1["id"])
        setattr(p2, field3, id)
        p2.remarks = obj_dict1["remarks"]
        obj_dict2_list.append(p2)

    session.add_all(obj_dict2_list)

async def insert_pojo_by_relation(session: AsyncSession, Pojo1: Type[Base], obj_dict1: dict, field1: str, Pojo2: Type[Base], field2: str, field3: str):
    id_list = obj_dict1[field1]
    obj_dict1.pop(field1)

    session.add(Pojo1(**obj_dict1))

    await insert_pojo_by_many(session, id_list, obj_dict1, Pojo2, field2, field3)

async def delete_pojo_by_relation(session: AsyncSession, Pojo1: Type[Base], id: str, Pojo2: Type[Base], field: str):
    await session.execute(delete(Pojo2).where(getattr(Pojo2, field) == id))

    await session.execute(delete(Pojo1).where(Pojo1.id == id))

async def update_pojo_by_relation(session: AsyncSession, Pojo1: Type[Base], obj_dict1: dict, field1: str, Pojo2: Type[Base], field2: str, field3: str):
    await session.execute(delete(Pojo2).where(getattr(Pojo2, field2) == obj_dict1["id"]))

    await insert_pojo_by_many(session, obj_dict1[field1], obj_dict1, Pojo2, field2, field3)

    obj_dict1.pop(field1)
    await session.execute(update(Pojo1).where(Pojo1.id == obj_dict1["id"]), obj_dict1)

